package com.htkj.demo

import kotlinx.coroutines.cancel
import android.os.Handler
import android.os.Looper
import android.util.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import okhttp3.WebSocket
import okhttp3.WebSocketListener
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.TimeUnit

class WebSocketManager private constructor(builder: Builder) {
    // 配置参数
    private val url: String
    private val reconnectInterval: Long // 重连间隔（毫秒）
    private val maxReconnectAttempts: Int // 最大重连次数（-1 表示无限重试）
    private val heartbeatInterval: Long // 心跳间隔（毫秒）
//    private val heartbeatTimeout: Long // 心跳超时（毫秒）
    private val connectTimeout: Long // 连接超时（毫秒）
    private val heartbeatErrorSum:Int

    // 状态管理（原子类确保线程安全）
    private var webSocket: WebSocket? = null
    private val isConnected = AtomicBoolean(false)
    private val reconnectAttempts = AtomicInteger(0)
    private var pageIndex = 0

    private var failHeartbeatNumber=0;

    // 协程作用域（使用 Dispatchers.IO 处理网络操作，与主线程隔离）
    private val coroutineScope = CoroutineScope(Dispatchers.IO)
    private var heartbeatJob: Job? = null // 心跳协程任务
    private var reconnectJob: Job? = null // 重连协程任务
//    private var heartbeatTimeoutJob: Job? = null // 心跳超时协程任务

    // 主线程 Handler（用于消息回调到主线程）
    private val mainHandler = Handler(Looper.getMainLooper())

    // 事件监听器（线程安全的列表）
    private val listeners = Collections.synchronizedList(mutableListOf<MyWebSocketListener>())

    init {
        url = builder.url
        reconnectInterval = builder.reconnectInterval
        maxReconnectAttempts = builder.maxReconnectAttempts
        heartbeatInterval = builder.heartbeatInterval
        connectTimeout = builder.connectTimeout
        heartbeatErrorSum=builder.heartbeatErrorSum
    }

    // 添加监听器
    fun addListener(listener: MyWebSocketListener) {
        listeners.add(listener)
    }

    // 移除监听器
    fun removeListener(listener: MyWebSocketListener) {
        listeners.remove(listener)
    }

    // 移除所有监听器
    fun removeAllListeners() {
        listeners.clear()
    }

    // 完全清理资源（断开连接、取消任务、清理监听器）
    fun clear() {
        removeAllListeners()
        stopHeartbeat()
        cancelReconnect()
        isConnected.set(false)
        webSocket?.cancel() // 取消WebSocket连接
        webSocket = null
        coroutineScope.cancel()  // 取消所有协程任务（防止内存泄漏）
        log("WebSocket资源已完全清理")
    }

    // 发起连接
    fun connect() {
        if (isConnected.get())  return

        val client = OkHttpClient.Builder()
            .connectTimeout(connectTimeout, TimeUnit.MILLISECONDS)
            .build()

        val request = Request.Builder()
            .url(url)
            .build()

        // 取消已有WebSocket连接（避免重复连接）
        webSocket?.cancel()
        // 创建新的WebSocket连接
        webSocket = client.newWebSocket(request,  object : WebSocketListener() {
            override fun onOpen(webSocket: WebSocket, response: Response) {
                isConnected.set(true)
                reconnectAttempts.set(0)  // 重置重连次数
                cancelReconnect() // 取消重连任务
                log("WebSocket连接成功")
                // 回调监听器（主线程）
                mainHandler.post  {
                    listeners.forEach  { it.onOpen(webSocket,  response) }
                }
                startHeartbeat() // 启动心跳
            }

            override fun onMessage(webSocket: WebSocket, text: String) {
                log("收到消息: $text")
                // 主线程处理消息（避免ANR）
                mainHandler.post  {
                    try {
                        if (isHeartbeatResponse(text)) {
                            resetHeartbeatTimeout() // 心跳响应：重置超时
                            return@post
                        }
                        // 回调监听器处理业务消息
                        listeners.forEach  { it.onMessage(webSocket,  text) }
                    } catch (e: Exception) {
                        log("消息处理异常: ${e.message}")
                    }
                }
            }

            override fun onClosed(webSocket: WebSocket, code: Int, reason: String) {
                handleDisconnect(code, reason)
                // 回调监听器（主线程）
                mainHandler.post  {
                    listeners.forEach  { it.onClosed(webSocket,  code, reason) }
                }
            }

            override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
                handleDisconnect(4000, t.message  ?: "Unknown error")
                // 回调监听器（主线程）
                mainHandler.post  {
                    listeners.forEach  { it.onFailure(webSocket,  t, response) }
                }
            }
        })
    }

    // 处理断开连接（触发重连逻辑）
    private fun handleDisconnect(code: Int, reason: String) {
        isConnected.set(false)
        stopHeartbeat() // 停止心跳
        log("连接关闭 (code: $code), 原因: $reason")

        // 非主动关闭（code != 4999）且未达最大重连次数时触发重连
        if (code != 4999 && (maxReconnectAttempts == -1 || reconnectAttempts.get()  < maxReconnectAttempts)) {
            val attempts = reconnectAttempts.incrementAndGet()
            log("第 $attempts 次重连... (间隔 ${reconnectInterval}ms)")
            startReconnect() // 启动重连协程
        }
    }

    // 启动心跳（协程 + flow 实现定时任务）
    private fun startHeartbeat() {
        // 取消已有心跳任务
        heartbeatJob?.cancel()
        // 启动新的心跳任务（每 heartbeatInterval 毫秒发送一次）
        heartbeatJob = flow {
            while (true) {
                emit(Unit)
                delay(heartbeatInterval) // 间隔发送
            }
        }.onEach {
            if (isConnected.get())  {
                webSocket?.send(createHeartbeatMessage()) // 发送心跳包
                log("发送心跳包")
//                startHeartbeatTimeout() // 启动心跳超时检测
                failHeartbeatNumber++;
                if(failHeartbeatNumber>heartbeatErrorSum){
                    handleDisconnect(4001, "心跳超时时间${failHeartbeatNumber}")
                    failHeartbeatNumber=0;
                }
            }
        }.launchIn(coroutineScope) // 在协程作用域中启动
    }

//    // 启动心跳超时检测（协程实现）
//    private fun startHeartbeatTimeout() {
//        // 取消已有超时任务
//        heartbeatTimeoutJob?.cancel()
//        // 启动超时任务（heartbeatTimeout 毫秒后未收到响应则断开连接）
//        heartbeatTimeoutJob = coroutineScope.launch  {
//            delay(heartbeatTimeout)
//            log("心跳超时，断开连接")
//            webSocket?.close(4001, "heartbeat timeout") // 主动关闭连接
//        }
//    }

    // 重置心跳超时（收到心跳响应时调用）
    private fun resetHeartbeatTimeout() {
//        heartbeatTimeoutJob?.cancel()
        failHeartbeatNumber=0;
        log("收到心跳响应，重置超时定时器")
    }

    // 停止心跳（断开连接时调用）
    private fun stopHeartbeat() {
        heartbeatJob?.cancel() // 取消心跳发送任务
//        heartbeatTimeoutJob?.cancel() // 取消心跳超时任务
        log("心跳任务已停止")
    }

    // 启动重连（协程实现）
    private fun startReconnect() {
        // 取消已有重连任务
        reconnectJob?.cancel()
        // 延迟 reconnectInterval 后执行重连
        reconnectJob = coroutineScope.launch  {
            delay(reconnectInterval)
            connect() // 发起重连
        }
    }

    // 取消重连任务
    private fun cancelReconnect() {
        reconnectJob?.cancel()
        log("重连任务已取消")
    }

    // 创建心跳消息
    private fun createHeartbeatMessage(): String {
        return """{"type":"ping","index":$pageIndex}"""
    }

    // 判断是否为心跳响应
    private fun isHeartbeatResponse(text: String): Boolean {
        return try {
            text.contains("\"type\":\"pong\"")
        } catch (e: Exception) {
            false
        }
    }

    fun send(message: String) {
        if (isConnected.get()) {
            webSocket?.send(message)
            log("发送消息成功: $message")
        } else {
            log("WebSocket未连接，无法发送消息！")
            mainHandler.post  {
                listeners.forEach  { it.onTocat("WebSocket未连接，无法发送消息！") }
            }
        }
    }

    fun setPageIndex(index: Int) {
        pageIndex = index
    }

    private fun log(message: String) {
        val time = java.text.SimpleDateFormat("HH:mm:ss",  java.util.Locale.getDefault())
            .format(java.util.Date())
        Log.d("WebSocket", "[$time] $message")
    }

    class Builder {
        var url: String = ""
            private set
        var reconnectInterval: Long = 3000
            private set
        var maxReconnectAttempts: Int = -1
            private set
        var heartbeatInterval: Long = 5000
            private set
        var heartbeatErrorSum: Int = 5
            private set
        var connectTimeout: Long = 10000
            private set

        fun url(url: String) = apply { this.url  = url }
        fun reconnectInterval(interval: Long) = apply { this.reconnectInterval  = interval }
        fun maxReconnectAttempts(attempts: Int) = apply { this.maxReconnectAttempts  = attempts }
        fun heartbeatInterval(interval: Long) = apply { this.heartbeatInterval  = interval }
        fun heartbeatErrorSum(sum: Int) = apply { this.heartbeatErrorSum  = sum }
        fun connectTimeout(timeout: Long) = apply { this.connectTimeout  = timeout }

        fun build(): WebSocketManager {
            require(url.isNotEmpty())  { "WebSocket连接地址(url)必填！" }
            return WebSocketManager(this)
        }
    }

    companion object {
        private fun cancelTimer(timer: Timer?) {
            timer?.cancel()
            timer?.purge()
        }
    }
}